﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Utils;
using PloobsEngine.Features;
using PloobsEngine.Commands;
using PloobsEngineDemo3;
using PloobsEngine.Light;
using BEPUphysics;
using PloobsEngine.Physic.PhysicObjects.BepuObject;

namespace Etapa1.Screens
{
    public class SandBoxScreen : SceneScreen
    {
        private BepuPhysicWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        ICamera cam;

        public SandBoxScreen(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                        
            engine.Game.IsFixedTimeStep = true;
        }
        
        public override void LoadContent(EngineStuff es)
        {
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            base.LoadContent(es);
            #region Models

            TerrainObject to = new TerrainObject("..\\Content\\Textures\\Untitled");
            SimpleTerrainModel stm = new SimpleTerrainModel(to, "..\\Content\\Textures\\Terraingrass", "..\\Content\\Textures\\rock", "..\\Content\\Textures\\sand", "..\\Content\\Textures\\snow");
            stm.LoadModelo();
            TerrainShader shader = new TerrainShader(TerrainType.MULTITEXTURE);
            shader.Initialize();
            Material mat = new Material(shader, MaterialType.DEFERRED);
            IObject obj3 = new SimpleObject(mat, to, stm);
            mundo.AddObject(obj3);

            {                
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        float x, y;
                        x = -i * 100;
                        y = -j * 100;

                        TreeModel tm = new TreeModel("..\\Content\\Trees\\Pine");
                        TreeShader ts = new TreeShader();
                        ts.Initialize();
                        TreeMaterial tmat = new TreeMaterial(ts);
                        GhostObject go = new GhostObject(new Vector3(x, to.Terrain.GetHeight(x, y), y), Matrix.Identity, new Vector3(0.05f));
                        IObject ox = new SimpleObject(tmat, go, tm);
                        mundo.AddObject(ox);
                    }
                }                
            }


            {
                List<Vector3> poss = new List<Vector3>();
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        float x, y;
                        x = i * 100;
                        y = j * 100;
                        poss.Add(new Vector3(x, to.Terrain.GetHeight(x, y), y));
                    }
                }
                BillboardModel bm = new BillboardModel(poss, "..\\Content\\Textures\\tree");
                CilindricGPUBilboardDeferred cb = new CilindricGPUBilboardDeferred();
                Material matfor = new Material(cb, MaterialType.DEFERRED);
                IObject obj2 = new SimpleObject(matfor, new DummyPhysicObject(), bm);
                mundo.AddObject(obj2);

            }


            {
                Matrix[] world = new Matrix[10 * 10];
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        float x, y;
                        x = i * 5;
                        y = j * 5;
                        Matrix m = Matrix.CreateWorld(new Vector3(x, to.Terrain.GetHeight(x, y), y), Vector3.Right, Vector3.Up);
                        //Matrix m = Matrix.CreateWorld(new Vector3(x, to.Terrain.GetHeight(x, y), y), StaticRandom.RandomDirection(), Vector3.Up);
                        world[i * 10 + j] = m;
                    }
                }
                OrientedPlaneModel bm = new OrientedPlaneModel(ref world, "..\\Content\\Textures\\grama2");
                PlanarOrientedDeferred cb = new PlanarOrientedDeferred();
                cb.Scale = new Vector2(5, 5);
                cb.Atenuation = new Vector4(0.4f, 0.4f, 0.4f, 1);
                Material matfor = new Material(cb, MaterialType.DEFERRED);
                IObject obj2 = new SimpleObject(matfor, new DummyPhysicObject(), bm);
                mundo.AddObject(obj2);
            }

            {
                Matrix[] world = new Matrix[10 * 10];
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        float x, y;
                        x = i * 5 + 100 + StaticRandom.RandomBetween(-5, 5);
                        y = j * 5 + 100 + StaticRandom.RandomBetween(-5, 5);
                        Vector3 dir = StaticRandom.RandomDirection();
                        dir.Y = 0;
                        Matrix m = Matrix.CreateWorld(new Vector3(x, to.Terrain.GetHeight(x, y), y), dir, Vector3.Up);
                        world[i * 10 + j] = m;
                    }
                }
                OrientedPlaneModel bm = new OrientedPlaneModel(ref world, "..\\Content\\Textures\\grama1");
                PlanarOrientedDeferred cb = new PlanarOrientedDeferred();
                cb.Scale = new Vector2(5, 5);
                cb.Atenuation = new Vector4(0.5f, 0.5f, 0.5f, 1);
                Material matfor = new Material(cb, MaterialType.DEFERRED);
                IObject obj2 = new SimpleObject(matfor, new DummyPhysicObject(), bm);
                mundo.AddObject(obj2);
            }


            //for (int i = 0; i < 1; i++)
            //{
            //    for (int j = 0; j < 1; j++)
            //    {
            //        SimpleModel sm = new SimpleModel("..\\Content\\Model\\specball");
            //        sm.LoadModelo();
            //        ///esses Modelos .fbx tem pra cima invertidos ...
            //        GhostObject pi = new GhostObject(new Vector3(10 * j, 40, 10 * i), Matrix.Identity, new Vector3(1));
            //        NormalDeferred shader = new NormalDeferred();
            //        shader.SpecularIntensity = 0.1f;
            //        shader.SpecularPower = 30;
            //        shader.Initialize(engine);
            //        ImpostorDeferredMaterial mat = new ImpostorDeferredMaterial(shader, engine);
            //        mat.DistanceToChangeToImpostor = 250;
            //        IObject obj3 = new SimpleObject(mat, pi, sm);
            //        mundo.AddObject(obj3);
            //    }
            //}

            //{
            //    SimpleModel sm = new SimpleModel("..\\Content\\Model\\cenario");
            //    sm.LoadModelo();
            //    IPhysicObject pi = new TriangleMeshObject(Vector3.Zero, sm);
            //    //CustomDeferred shader = new CustomDeferred(false, false, false, false);
            //    NormalDeferred shader = new NormalDeferred();
            //    shader.SpecularIntensity = 0;
            //    shader.SpecularPower = 0;
            //    shader.Initialize();
            //    IMaterial mat = new Material(shader, MaterialType.DEFERRED);
            //    IObject obj3 = new SimpleObject(mat, pi, sm);
            //    mundo.AddObject(obj3);
            //}


            #endregion

            cam = new CameraFirstPerson(true);
            cam.FarPlane = 3000;

            LightThrowBepu lt = new LightThrowBepu(mundo, engine);

            #region NormalLight
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);
            //dr.isDebug = true;
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;
            mundo.AddCamera(cam);
            this.World = mundo;

            
            FogPostEffect fog = new FogPostEffect(0.001f, FogType.EXPONENCIALSQUARED);
            dr.AddPostEffect(fog);

            //SkyDome sk = new SkyDome();
            //engine.AddComponent(sk);

            //SkyDomeParametersCommand su = new SkyDomeParametersCommand(cam, "..\\Content\\Textures\\cloudMap");
            //CommandProcessor.getCommandProcessor().SendCommandAssyncronous(su);

        }

        



    }
}

